package com.winning.gjhlht.ihe.job.thread;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.sql.Clob;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;

import oracle.sql.CLOB;

import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.cownew.ctk.common.RandomGUID;
import com.framework.FrameworkServlet;
import com.winning.common.Constans;
import com.winning.common.beans.ihe.IHERequestBodyBean;
import com.winning.common.beans.ihe.IHERequestItemBean;
import com.winning.common.beans.xmlTemp.XMLTempConfigBean;
import com.winning.common.data.service.PlatBasicDataService;
import com.winning.common.tools.XMLTool;
import com.winning.core.net.CXFWebserviceClent;

/**
 * 类名称：IHERegistrationRequestTask
 * 类描述：数据上传线程任务
 * 创建人：liuwensheng
 * 创建时间：2016-12-13 下午3:03:41
 * 修改人：liuwensheng
 * 修改时间：2016-12-13 下午3:03:41
 * 修改备注：
 */
public class IHERegistrationRequestTask extends TimerTask {
    private static Logger LOGGER = Logger.getLogger(Constans.LOG4J_PBS_LOGGER_ID);

    private PlatBasicDataService platBasicDataService = null;

    //判断线程是否执行完毕
    private boolean isOver = false;

    //消息XML对象
    private Document documentSource = null;

    //业务表数据源
    private List<Map<String, Object>> registrationRequestInfoDataList = null;

    //消息XML模板配置实体
    private IHERequestBodyBean iheRequestBodyBean = null;


    //接口模板文件信息
    private XMLTempConfigBean xmlTempConfigBean = null;

    public IHERegistrationRequestTask(Document documentSource, List<Map<String, Object>> registrationRequestInfoDataList, IHERequestBodyBean iheRequestBodyBean, PlatBasicDataService platBasicDataService, XMLTempConfigBean xmlTempConfigBean) {
        this.documentSource = documentSource;

        this.registrationRequestInfoDataList = registrationRequestInfoDataList;

        this.iheRequestBodyBean = iheRequestBodyBean;

        this.platBasicDataService = platBasicDataService;

        this.xmlTempConfigBean = xmlTempConfigBean;
    }

    @Override
    public void run() {
        try {
            //wsdl服务路径地址
            String wsdlURL = iheRequestBodyBean.getWebserviceURL();

            //平台webservice接口服务名称
            String actionMethodName = iheRequestBodyBean.getActionMethodName();

            //webservice开发的接口方法名称
            String webserviceMethodName = iheRequestBodyBean.getWebserviceMethodName();

            String xmlStr = documentSource.asXML() == null ? "" : documentSource.asXML();

            xmlStr = xmlStr.substring(39, xmlStr.length());

            //填充所有信息, 并发送请求
            for (Iterator<Map<String, Object>> iterator = registrationRequestInfoDataList.iterator(); iterator.hasNext(); ) {
                if (iterator != null) {
                    //一个请求的基本信息, key值为表字段名称，统一为大写
                    Map<String, Object> registrationRequestInfoMap = iterator.next();

                    //生成一个请求的IHE入参xml模板对象
                    Document xmlDoc = XMLTool.getDocumentFromXMLString(xmlStr, true);

                    xmlDoc = createOneRegistrationXMLInfoHandler(xmlDoc, registrationRequestInfoMap, iheRequestBodyBean);

                    String requestXMLValue = xmlDoc.asXML();

                    String requestXMLMessage = requestXMLValue.substring(39, requestXMLValue.length());

                    LOGGER.debug("--> 一条请求消息XML结构:" + requestXMLMessage);
                    LOGGER.info("--> 一条请求消息XML生成");

                    if (webserviceMethodName == null || actionMethodName == null || "".equals(webserviceMethodName) || "".equals(actionMethodName)) {
                        LOGGER.info("--> 配置异常，配置的webservice接口方法名称为:[" + webserviceMethodName + "]; 处理事件名称为:[" + actionMethodName + "]");
                    } else {

                        LOGGER.info("--> 配置的webservice接口方法名称为:[" + webserviceMethodName + "]; 处理事件名称为:[" + actionMethodName + "];处理路径为：[" + wsdlURL + "]");

                        //调用互联互通服务,采用的是CXF框架
                        CXFWebserviceClent.sendAxisFWebserviceRequestHandler(documentSource, platBasicDataService, iheRequestBodyBean, requestXMLMessage, registrationRequestInfoMap, xmlTempConfigBean);
                        //CXFWebserviceClent.sendAxisFWebserviceRequestHandler(documentSource, platBasicDataService, iheRequestBodyBean, requestXMLMessage, registrationRequestInfoMap,xmlTempConfigBean);
                    }
                }
            }

            registrationRequestInfoDataList.removeAll(registrationRequestInfoDataList);
            registrationRequestInfoDataList = null;
        } catch (Exception e) {
            //打印异常堆栈信息
            LOGGER.error(e, e.fillInStackTrace());
            e.printStackTrace();
        } finally {
            //线程结束状态
            isOver = true;

            System.gc();
        }
    }

    /**
     * 创建一个注册请求的XML信息 <br/>
     * 方法名称: createOneRegistrationXMLInfoHandler
     *
     * @param
     * @return Document  返回类型说明<br/>
     * @throws <br/>
     * @author liuwensheng@winning.com.cn<br/>
     * 创建时间：2016-12-13/上午9:46:17<br/>
     */
    private Document createOneRegistrationXMLInfoHandler(Document xmlDoc, Map<String, Object> patientPersionInfoMap, IHERequestBodyBean iheRequestBodyBean) {
        List<IHERequestItemBean> iheRequestItemList = iheRequestBodyBean.getIheRequestItemList();

        for (Iterator<IHERequestItemBean> IHERequestItemBeanIterator = iheRequestItemList.iterator(); IHERequestItemBeanIterator.hasNext(); ) {
            IHERequestItemBean iheRequestItemBean = IHERequestItemBeanIterator.next();

            String xPathTypeValue = iheRequestItemBean.getxPathType();

            String xPathValue = iheRequestItemBean.getxPathValue();

            //数据类型
            String dataTypeValue = iheRequestItemBean.getDataType();

            //格式化字符串
            String dateFormatterValue = iheRequestItemBean.getDataFormatter();

            //获取本地业务表列名称，从业务表结果集总获取数据
            String columnName = iheRequestItemBean.getLocalColumnName();

            String columnValue = "";

            //如果columnName为{GUID}表达式，则为随机数生成GUID
            if (Constans.GUID_TYPE.equals(dataTypeValue)) {
                //自动生成唯一主键
                columnValue = new RandomGUID().toString();
            } else if (Constans.DATE_TYPE.equals(dataTypeValue)) {
                //时间类型，数据库统一为标准格式：YYYY-MM-DD hh:mm:ss; 再按照配置的时间格式转换

            }
//			else if(Constans.CLOB_TYPE.equals(dataTypeValue))
//			{
//				
//				LOGGER.info("--> CLOB 类型开始转码");
//				
//				String value = (String)patientPersionInfoMap.get(columnName);
//				
//				columnValue = changeXMLBase64Encoding(value);
//				
//				LOGGER.info("-->修改编码后的base64编码:"+columnValue);
//				
//			}

            //处理xml数据，转换成系统需要的base64编码
            else if (Constans.XML_TYPE.equals(dataTypeValue)) {
                String value = (String) patientPersionInfoMap.get(columnName);

                //转base64编码
                columnValue = getBASE64(value);

                LOGGER.debug("--> 生成好的Base64编码:" + columnValue);

            } else {
                columnValue = (String) patientPersionInfoMap.get(columnName);

            }

            //如果数据库返回结果为空的处理, 需要判断是否提供默认值设置
            if (columnValue == null || columnValue.length() == 0) {
                //如果提供了默认值，则设置默认值
                if (iheRequestItemBean.getDefaultValue() != null && !"".equals(iheRequestItemBean.getDefaultValue())) {
                    columnValue = iheRequestItemBean.getDefaultValue();
                } else {
                    columnValue = "";
                }
            }

            //如果配置的xpath路径是获取元素节点对象，则直接给xml元素节点文本赋值<test>...</test>
            if (Constans.XML_ELEMENT_TYPE.equals(xPathTypeValue)) {
                Element xpathElement = XMLTool.selectElementObjByXPath(xmlDoc, xPathValue);


                if (xpathElement != null) {
                    //给xml元素节点文本赋值
                    xpathElement.setText(columnValue);
                }
            }
            //如果配置的xpath路径是获取属性对象，则直接给属性对象赋值<test value="...">...</test>
            else if (Constans.XML_ATTRIBUTE_TYPE.equals(xPathTypeValue)) {
                Attribute attribute = XMLTool.selectAttributeObjectByXPath(xmlDoc, xPathValue);

                if (attribute != null) {
                    //给xml元素节点中的属性赋值
                    attribute.setValue(columnValue);
                }
            }
        }

        return xmlDoc;
    }

    public boolean isOver() {
        return isOver;
    }


    /**
     * 根据不同的编码解析Base64字符串
     * 方法名称: decodeBASE64
     *
     * @param
     * @return String  返回类型说明<br/>
     * @throws <br/>
     * @author lenovo@winning.com.cn<br/>
     * 创建时间：2017-1-19/上午12:08:53<br/>
     */
    public static String decodeBASE64(String base64Str, String encoding) {
        if (base64Str == null) {
            return null;
        }
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(base64Str);
            return new String(b, encoding);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 生成Base64编码
     * 方法名称: getBASE64
     *
     * @param
     * @return String  返回类型说明<br/>
     * @throws <br/>
     * @author lenovo@winning.com.cn<br/>
     * 创建时间：2017-1-19/上午12:08:29<br/>
     */
    public static String getBASE64(String cdaContentValue) {
        String base64Str = "";

        if (cdaContentValue == null) {
            return null;
        }

        try {
            base64Str = (new sun.misc.BASE64Encoder()).encode(cdaContentValue.getBytes("UTF-8")).replace("\n", "").replace("\r", "");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return base64Str;
    }


    /**
     * 将数据库查询出的base64格式解码，转换成utf-8编码
     * 方法名称: changeXMLBase64Encoding
     *
     * @param
     * @return String  返回类型说明<br/>
     * @throws <br/>
     * @author lenovo@winning.com.cn<br/>
     * 创建时间：2017-1-19/上午12:12:50<br/>
     */
    private String changeXMLBase64Encoding(String base64Str) {
        String returnStr = "";
        try {
            //解码生成XML数据
            String docString = decodeBASE64(base64Str, "gb2312");

            docString = new String(docString.getBytes("utf-8"), "utf-8");

            //生成XML对象
            Document document = null;
            SAXReader saxReader = new SAXReader();
            saxReader.setEncoding("utf-8");
            docString = docString.replaceAll("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", "");
            docString = docString.replaceAll("\\&", "&amp;");
            document = saxReader.read(new ByteArrayInputStream(docString.getBytes("UTF-8")));


            String cdaFile = new RandomGUID().toString();

            LOGGER.info("-->生成XML文档:" + document.asXML());

            //写入本地文件系统
            writeCDAToFile(document, cdaFile);

            //读取写入的字符串
            SAXReader saxReaderFile = new SAXReader();

            saxReaderFile.setEncoding("UTF-8");
            //文件夹路径
            String direPath = "E:/thirdParty/cda/";

            String filePath = direPath + cdaFile + ".xml";

            //LOGGER.info("-->生成文件的路径:"+filePath);

            //读取本地写入的文件
            Document resultDocument = saxReaderFile.read(new File(filePath));

            //编码成UTF-8对象
            returnStr = getBASE64(resultDocument.asXML());

        } catch (Exception e) {

            LOGGER.error(e, e.fillInStackTrace());
        }

        return returnStr;
    }


    /**
     * 将xml对象写入本地
     * 方法名称: writeCDAToFile
     *
     * @param
     * @return String  返回类型说明<br/>
     * @throws <br/>
     * @author lenovo@winning.com.cn<br/>
     * 创建时间：2017-1-19/上午12:10:56<br/>
     */
    public static String writeCDAToFile(Document document, String cdaFile) {
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");// 设置XML文件的编码格式


        String direPath = "E:/thirdParty/cda/";
        String filePath = direPath + cdaFile + ".xml";

        File direFile = new File(direPath);
        //创建文件夹
        if (!direFile.exists() && !direFile.isDirectory()) {
            try {
                direFile.mkdir();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        try {
            FileOutputStream fos = new FileOutputStream(filePath);
//			XMLWriter xmlWriter = new XMLWriter(new FileWriter(filePath), format);
            XMLWriter xmlWriter = new XMLWriter(fos, format);
//			String cdaStr= document.asXML();
//			cdaStr=cdaStr.replace("type=", "xsi:type=");
//			document=DocumentHelper.parseText(cdaStr);
            xmlWriter.write(document);
            xmlWriter.close();
        } catch (Exception e) {
            e.printStackTrace();

            return null;
        }
        return null;
    }


}
